import sys

import numpy as np

# https://numpy.org/doc/stable/user/quickstart.html

a = np.arange(15).reshape(3, 5)
print(a)
print(a.shape)

print(a.ndim)
print(a.dtype.name)
print(a.itemsize)
print(a.size)
print(type(a))

b = np.array([6, 7, 8])
print(b)
print(type(b))

# array 还可以将序列的序列转换成二维数组，将序列的序列的序列转换成三维数组，等等。
b = np.array([(1.5, 2, 3), (4, 5, 6)])
print(b)
print(b.shape)

# 也可以在创建时显式指定数组的类型：
c = np.array([[1, 2], [3, 4]], dtype=complex)
print(c)

# 函数zeros创建一个由0组成的数组，函数 ones创建一个完整的数组，函数empty 创建一个数组，其初始内容是随机的，取决于内存的状态。默认情况下，创建的数组的dtype是 float64 类型的。
print(np.zeros((3, 4)))
# dtype can also be specified
print(np.ones((2, 3, 4), dtype=np.int16))
# uninitialized, output may vary
print(np.empty((2, 3)))

# 为了创建数字组成的数组，NumPy提供了一个类似于range的函数，该函数返回数组而不是列表。
print(np.arange(10, 30, 5))

# it accepts float arguments
a = np.arange(0, 2, 0.3)
print(a)

# 当arange与浮点参数一起使用时，由于有限的浮点精度，通常不可能预测所获得的元素的数量。出于这个原因，通常最好使用linspace函数来接收我们想要的元素数量的函数，而不是步长（step）：
from numpy import pi

# 9 numbers from 0 to 2
a = np.linspace(0, 2, 9)
print(a)

# useful to evaluate function at lots of points
x = np.linspace(0, 2 * pi, 100)
print(x)
f = np.sin(x)
print(f)

# ## 打印数组
a = np.arange(6)  # 1d array
print(a)

b = np.arange(12).reshape(4, 3)  # 2d array
print(b)

c = np.arange(24).reshape(2, 3, 4)  # 3d array
print(c)

# 如果数组太大而无法打印，NumPy会自动跳过数组的中心部分并仅打印角点：
print(np.arange(10000))

print(np.arange(10000).reshape(100, 100))
# 要禁用此行为并强制NumPy打印整个数组，可以使用更改打印选项set_printoptions
np.set_printoptions(threshold=sys.maxsize)  # sys module should be imported

# 基本操作
a = np.array([20, 30, 40, 50])
b = np.arange(4)
print(a)
print(b)
c = a - b
print(c)
print(b ** 2)
print(10 * np.sin(a))
print(a < 35)

# 与许多矩阵语言不同，乘积运算符*在NumPy数组中按元素进行运算。矩阵乘积可以使用@运算符（在python> = 3.5中）或dot函数或方法执行：
A = np.array([[1, 1],
              [0, 1]])
B = np.array([[2, 0],
              [3, 4]])
print(A)
print(B)

print(A * B)
print(A @ B)
print(A.dot(B))

# 某些操作（例如+=和 *=）会更直接更改被操作的矩阵数组而不会创建新矩阵数组。
a = np.ones((2, 3), dtype=int)
print(a)
b = np.random.random((2, 3))
print(b)
a *= 3
print(a)
b += a
print(b)
# a += b

# 当使用不同类型的数组进行操作时，结果数组的类型对应于更一般或更精确的数组（称为向上转换的行为）。
a = np.ones(3, dtype=np.int32)
print(a)
b = np.linspace(0, pi, 3)
print(b)
print(b.dtype.name)
c = a + b
print(c)
d = np.exp(c * 1j)
print(d)
print(d.dtype.name)

# 许多一元操作，例如计算数组中所有元素的总和，都是作为ndarray类的方法实现的。
a = np.random.random((2, 3))
print(a)
print(a.sum())
print(a.min())
print(a.max())

# 默认情况下，这些操作适用于数组，就像它是一个数字列表一样，无论其形状如何。但是，通过指定axis 参数，您可以沿数组的指定轴应用操作：
b = np.arange(12).reshape(3, 4)
print(b)
print(b.sum(axis=0))
print(b.min(axis=1))
print(b.cumsum(axis=1))
